This week we started working with microcontrollers. With microcontrollers we need some hardware to control. So we got same basic hardware kits. We also tried soldering. I soldered 8x8 LED matrix kit with MAX7219 IC. This is how it turned out:
It is definetely not perfect i could have done a better job, but it works, so not so bad. For my excuse, it was my first time soldering SMD component with standart soldering iron, designed for through hole components. Here it is working, showing 8x8 bitman of an apple.
I decided that i want to create a classical snake game using this 8x8 LED matrix and 4 buttons. All controlled by Arduino Nano. Here is it wired on breadboard. It is a bit messy, but thats expected when using breadboard.
And here is wiring diagram.
Unfortunately Arduino Nano only has 2 Hardware Interrupt pins. I need 4 for each button. Luckily you can use almost all pins on Arduino as Pin Change Interrupts. There is a drawback though. All pins on same Pin Change Port will trigger the same interrupt. We also can't specify, if we want to trigger the interrupt on rising or falling edge. We need to find this out all by ourselfs. This is how i did it.
void setup() {
pinMode(8, INPUT);
pinMode(9, INPUT);
pinMode(10, INPUT);
pinMode(12, INPUT);
PCICR |= B00000100;
PCMSK2 |= B00010111;
}
void loop(){
}
ISR (PCINT2_vect){
if(digitalRead(8) == HIGH){
dir = LEFT;
}
else if(digitalRead(9) == HIGH){
dir = DOWN;
}
else if(digitalRead(10) == HIGH){
dir = UP;
}
else if(digitalRead(12) == HIGH){
dir = RIGTH;
}
}
Unfortunately the buttons sometimes dont do anything, even though they are pressed. It often results in players death in snake game, which is a bit frustrating. I will try to dinf better solution.
Than i prepared snake game code in VSCode in pure C. Which was much faster for debugging. Here is main function of the snake game. Full code can be found on my GitLab page.
void refresh(void){
Serial.println(dir);
int temp_last_row = 0;
int temp_last_col = 0;
// shift body one back
if(snake.snake_len > 0){
temp_last_row = snake.snake_body[snake.snake_len -1][0];
temp_last_col = snake.snake_body[snake.snake_len -1][0];
}
else{
temp_last_row = snake.snake_head[0];
temp_last_col = snake.snake_head[1];
}
for(int i = snake.snake_len-1; i > 0; --i){
snake.snake_body[i][0] = snake.snake_body[i -1][0];
snake.snake_body[i][1] = snake.snake_body[i -1][1];
}
if(snake.snake_len > 0){
snake.snake_body[0][0] = snake.snake_head[0];
snake.snake_body[0][1] = snake.snake_head[1];
}
// move head
if(dir == UP){
if(snake.snake_head[0] == 0){
snake.snake_head[0] = 7;
}
else{
snake.snake_head[0] -= 1;
}
}else if(dir == DOWN){
snake.snake_head[0] = (snake.snake_head[0] + 1)%8;
}else if(dir == LEFT){
if(snake.snake_head[1] == 0){
snake.snake_head[1] = 7;
}
else{
snake.snake_head[1] -= 1;
}
}else if(dir == RIGTH){
snake.snake_head[1] = (snake.snake_head[1] + 1)%8;
}
if(apple_head_collision()){
snake.snake_body[snake.snake_len][0] = temp_last_row;
snake.snake_body[snake.snake_len][0] = temp_last_col;
snake.snake_len++;
gen_apple();
}
else if(head_body_collision()){
reset_snake();
}
if(snake.snake_len >= 64){
reset_snake();
}
draw_snake();
return;
}
And here it is working in real life!
Later I have decided, that i wanted to build a box for it, and have it as mini arcade game.
Here is the design:
Unfortunately i discovered our shools laser cutter limit. It would seem, that 6,5 mm birch plywood is too big of a bite for it. A had to cut out the last 1 - 2 mm, that waren't cut by laser cutter, by hand. I tried multiple sweeps with refocusing the laser and it still wasn't enough. At one point it even started burning. Anyways here it is assembled:
And here it is running, with better button readings. If you hold the button for short time, rather than pressing it quickly it works pretty well.